{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#数据量太大，pdandas不能一次讲所有数据读入\n",
    "#也可以用pandas,一次读取部分数据，可以参考：https://www.cnblogs.com/datablog/p/6127000.html\n",
    "#import pandas as pd\n",
    "\n",
    "import numpy as np\n",
    "import scipy.sparse as ss\n",
    "import scipy.io as sio\n",
    "#保存数据\n",
    "import cPickle\n",
    "#event的特征需要编码\n",
    "from utils import FeatureEng\n",
    "from sklearn.preprocessing import normalize\n",
    "#相似度/距离\n",
    "import scipy.spatial.distance as ssd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "number of records :3137972\n"
     ]
    }
   ],
   "source": [
    "#读取数据，并统计有多少不同的events\n",
    "#其实EDA.ipynb中用read_csv已经统计过了\n",
    "lines = 0\n",
    "fin = open(\"events.csv\", 'rb')\n",
    "#找到用C/C++的感觉了\n",
    "#字段：event_id, user_id,start_time, city, state, zip, country, lat, and lng， 101 columns of words count\n",
    "fin.readline() # skip header，列名行\n",
    "for line in fin:\n",
    "    cols = line.strip().split(\",\")\n",
    "    lines += 1\n",
    "fin.close()\n",
    "\n",
    "print(\"number of records :%d\" % lines)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "number of events in train & test :13418\n"
     ]
    }
   ],
   "source": [
    "#读取训练集和测试集中出现过的活动列表\n",
    "eventIndex = cPickle.load(open(\"PE_eventIndex.pkl\", 'rb'))\n",
    "n_events = len(eventIndex)\n",
    "\n",
    "print(\"number of events in train & test :%d\" % n_events)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "FE = FeatureEng()\n",
    "\n",
    "fin = open(\"events.csv\", 'rb')\n",
    "\n",
    "#字段：event_id, user_id,start_time, city, state, zip, country, lat, and lng， 101 columns of words count\n",
    "fin.readline() # skip header\n",
    "\n",
    "#start_time, city, state, zip, country, lat, and lng\n",
    "eventPropMatrix = ss.dok_matrix((n_events, 7))\n",
    "\n",
    "#词频特征\n",
    "eventContMatrix = ss.dok_matrix((n_events, 101))\n",
    "\n",
    "for line in fin.readlines():\n",
    "    cols = line.strip().split(\",\")\n",
    "    eventId = str(cols[0])\n",
    "    \n",
    "    if eventIndex.has_key(eventId):  #在训练集或测试集中出现\n",
    "        i = eventIndex[eventId]\n",
    "  \n",
    "        #event的特征编码，这里只是简单处理，其实开始时间，地点等信息很重要\n",
    "        eventPropMatrix[i, 0] = FE.getJoinedYearMonth(cols[2]) # start_time\n",
    "        eventPropMatrix[i, 1] = FE.getFeatureHash(cols[3]) # city\n",
    "        eventPropMatrix[i, 2] = FE.getFeatureHash(cols[4]) # state\n",
    "        eventPropMatrix[i, 3] = FE.getFeatureHash(cols[5]) # zip\n",
    "        eventPropMatrix[i, 4] = FE.getFeatureHash(cols[6]) # country\n",
    "        eventPropMatrix[i, 5] = FE.getFloatValue(cols[7]) # lat\n",
    "        eventPropMatrix[i, 6] = FE.getFloatValue(cols[8]) # lon\n",
    "        \n",
    "        #词频\n",
    "        for j in range(9, 110):\n",
    "            eventContMatrix[i, j-9] = cols[j]\n",
    "fin.close()\n",
    "\n",
    "#用L2模归一化,Kmeans聚类基于L2距离\n",
    "eventPropMatrix = normalize(eventPropMatrix,\n",
    "    norm=\"l2\", axis=0, copy=False)\n",
    "sio.mmwrite(\"EV_eventPropMatrix\", eventPropMatrix)\n",
    "\n",
    "#词频，可以考虑我们用这部分特征进行聚类，得到活动的genre\n",
    "eventContMatrix = normalize(eventContMatrix,\n",
    "    norm=\"l2\", axis=0, copy=False)\n",
    "sio.mmwrite(\"EV_eventContMatrix\", eventContMatrix)\n",
    "\n",
    "\n",
    "# calculate similarity between event pairs based on the two matrices\n",
    "eventPropSim = ss.dok_matrix((n_events, n_events))\n",
    "eventContSim = ss.dok_matrix((n_events, n_events))\n",
    "\n",
    "#读取在测试集和训练集中出现的活动对\n",
    "uniqueEventPairs = cPickle.load(open(\"PE_uniqueEventPairs.pkl\", 'rb'))\n",
    "\n",
    "for e1, e2 in uniqueEventPairs:\n",
    "    #i = eventIndex[e1]\n",
    "    #j = eventIndex[e2]\n",
    "    i = e1\n",
    "    j = e2\n",
    "    \n",
    "    #非词频特征，采用Person相关系数作为相似度\n",
    "    if not eventPropSim.has_key((i,j)):\n",
    "        epsim = ssd.correlation(eventPropMatrix.getrow(i).todense(),\n",
    "            eventPropMatrix.getrow(j).todense())\n",
    "        \n",
    "        eventPropSim[i, j] = epsim\n",
    "        eventPropSim[j, i] = epsim\n",
    "    \n",
    "    #对词频特征，采用余弦相似度，也可以用直方图交/Jacard相似度\n",
    "    if not eventContSim.has_key((i,j)):\n",
    "        ecsim = ssd.cosine(eventContMatrix.getrow(i).todense(),\n",
    "            eventContMatrix.getrow(j).todense())\n",
    "    \n",
    "        eventContSim[i, j] = epsim\n",
    "        eventContSim[j, i] = epsim\n",
    "    \n",
    "sio.mmwrite(\"EV_eventPropSim\", eventPropSim)\n",
    "sio.mmwrite(\"EV_eventContSim\", eventContSim)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "matrix([[0., 0., 0., ..., 0., 0., 0.]])"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eventPropSim.getrow(0).todense()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "## 导入工具包\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "#特征编码\n",
    "from utils import FeatureEng\n",
    "\n",
    "from sklearn.preprocessing import normalize\n",
    "from sklearn import metrics"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#读取数据\n",
    "import scipy.io as sio\n",
    "eventContMatrix = sio.mmread(\"EV_eventContMatrix\") "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "from sklearn.cluster import MiniBatchKMeans\n",
    "\n",
    "# 一个参数点（聚类数据为K）的模型，并评价聚类算法性能\n",
    "def K_cluster_analysis(K, df):\n",
    "    print(\"K-means begin with clusters: {}\".format(K));\n",
    "    \n",
    "    #K-means,在训练集上训练\n",
    "    km = MiniBatchKMeans(n_clusters = K)\n",
    "    km.fit(df)\n",
    "    \n",
    "    #保存预测结果\n",
    "    cluster_result = km.predict(df)\n",
    "\n",
    "    # K值的评估标准\n",
    "    #常见的方法有轮廓系数Silhouette Coefficient和Calinski-Harabasz Index\n",
    "    #这两个分数值越大则聚类效果越好\n",
    "    #CH_score = metrics.calinski_harabaz_score(X_train,mb_kmeans.predict(X_train))\n",
    "    CH_score = metrics.silhouette_score(df,cluster_result)   \n",
    "    print(\"CH_score: {}\".format(CH_score))\n",
    "\n",
    "    return CH_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K-means begin with clusters: 10\n",
      "CH_score: 0.0926409579241\n",
      "K-means begin with clusters: 20\n",
      "CH_score: 0.099908183338\n",
      "K-means begin with clusters: 30\n",
      "CH_score: -0.0234797065614\n",
      "K-means begin with clusters: 40\n",
      "CH_score: -0.0390240151484\n",
      "K-means begin with clusters: 50\n",
      "CH_score: -0.0258422328957\n",
      "K-means begin with clusters: 60\n",
      "CH_score: -0.085365659272\n",
      "K-means begin with clusters: 70\n",
      "CH_score: -0.141575334804\n",
      "K-means begin with clusters: 80\n",
      "CH_score: -0.159686920828\n",
      "K-means begin with clusters: 90\n",
      "CH_score: -0.187506494936\n",
      "K-means begin with clusters: 100\n",
      "CH_score: -0.0754154220482\n"
     ]
    }
   ],
   "source": [
    "# 设置超参数（聚类数目K）搜索范围\n",
    "CH_scores = []\n",
    "Ks = [10,20,30,40,50,60,70,80,90,100]\n",
    "for K in Ks:\n",
    "    ch = K_cluster_analysis(K, eventContMatrix)\n",
    "    CH_scores.append(ch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.09264095792414108, 0.09990818333801706, -0.023479706561383838, -0.039024015148405373, -0.025842232895744624, -0.08536565927201627, -0.14157533480355058, -0.15968692082767366, -0.1875064949364692, -0.0754154220481687]\n"
     ]
    }
   ],
   "source": [
    "print CH_scores"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x7f611db31150>]"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\niIhU8b9zthx7QOByvAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f611de2ced0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制不同PCA维数下模型的性能，找到最佳模型／参数（分数最高）\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "\n",
    "plt.plot(Ks, np.array(CH_scores), 'b-')"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
